home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / utils / adt / varlena.c < prev   
Encoding:
C/C++ Source or Header  |  1992-08-27  |  9.4 KB  |  480 lines

  1. /*
  2.  * varlena.c --
  3.  *     Functions for the variable-length built-in types.
  4.  *
  5.  * $Header: /private/postgres/src/utils/adt/RCS/varlena.c,v 1.17 1992/08/25 17:47:38 mer Exp $
  6.  */
  7.  
  8. #include <ctype.h>
  9. #include <strings.h>
  10.  
  11. #include "tmp/postgres.h"
  12. #include "utils/log.h"
  13. #include "utils/palloc.h"
  14. #include "utils/builtins.h"
  15. struct varlena *shove_bytes ARGS((unsigned char *stuff , int len ));
  16.  
  17.         /* ========== USER I/O ROUTINES ========== */
  18.  
  19.  
  20. #define    VAL(CH)        ((CH) - '0')
  21. #define    DIG(VAL)    ((VAL) + '0')
  22.  
  23. /*
  24.  *    byteain        - converts from printable representation of byte array
  25.  *
  26.  *    Non-printable characters must be passed as '\nnn' (octal) and are
  27.  *    converted to internal form.  '\' must be passed as '\\'.
  28.  *    elog(WARN, ...) if bad form.
  29.  *
  30.  *    BUGS:
  31.  *        The input is scaned twice.
  32.  *        The error checking of input is minimal.
  33.  */
  34. struct varlena *
  35. byteain(inputText)
  36.     char    *inputText;
  37. {
  38.     register char    *tp;
  39.     register char    *rp;
  40.     register int    byte;
  41.     struct varlena    *result;
  42.  
  43.     if (inputText == NULL)
  44.         elog(WARN, "Bad input string for type bytea");
  45.  
  46.     for (byte = 0, tp = inputText; *tp != '\0'; byte++)
  47.         if (*tp++ == '\\')
  48.         {
  49.             if (*tp == '\\')
  50.                 tp++;
  51.             else if (!isdigit(*tp++) ||
  52.                  !isdigit(*tp++) ||
  53.                  !isdigit(*tp++))
  54.                 elog(WARN, "Bad input string for type bytea");
  55.         }
  56.     tp = inputText;
  57.     byte += sizeof(int32);                    /* varlena? */
  58.     result = (struct varlena *) palloc(byte);
  59.     result->vl_len = byte;                    /* varlena? */
  60.     rp = result->vl_dat;
  61.     while (*tp != '\0')
  62.         if (*tp != '\\' || *++tp == '\\')
  63.             *rp++ = *tp++;
  64.         else {
  65.             byte = VAL(*tp++);
  66.             byte <<= 3;
  67.             byte += VAL(*tp++);
  68.             byte <<= 3;
  69.             *rp++ = byte + VAL(*tp++);
  70.         }
  71.     return(result);
  72. }
  73.  
  74. /*
  75.  * Shoves a bunch of memory pointed at by bytes into varlena.
  76.  * BUGS:  Extremely unportable as things shoved can be string
  77.  * representations of structs, etc.
  78.  */
  79.  
  80. struct varlena *
  81. shove_bytes(stuff, len)
  82.  
  83. unsigned char *stuff;
  84. int len;
  85.  
  86. {
  87.     struct varlena *result;
  88.  
  89.     result = (struct varlena *) palloc(len + sizeof(int32));
  90.     result->vl_len = len;
  91.     bcopy(stuff + sizeof(int32), result->vl_dat, len - sizeof(int32));
  92.     return(result);
  93. }
  94.  
  95.  
  96.  
  97. /*
  98.  *    byteaout    - converts to printable representation of byte array
  99.  *
  100.  *    Non-printable characters are inserted as '\nnn' (octal) and '\' as
  101.  *    '\\'.
  102.  *
  103.  *    NULL vlena should be an error--returning string with NULL for now.
  104.  */
  105. char *
  106. byteaout(vlena)
  107.     struct varlena    *vlena;
  108. {
  109.     register char    *vp;
  110.     register char    *rp;
  111.     register int    val;        /* holds unprintable chars */
  112.     int        i;
  113.     int        len;
  114.     static    char    *result;
  115.  
  116.     if (vlena == NULL) {
  117.         result = (char *) palloc(2);
  118.         result[0] = '-';
  119.         result[1] = '\0';
  120.         return(result);
  121.     }
  122.     vp = vlena->vl_dat;
  123.     len = 1;        /* empty string has 1 char */
  124.     for (i = vlena->vl_len - sizeof(int32); i != 0; i--)    /* varlena? */
  125.         if (*vp == '\\')
  126.             len += 2;
  127.         else if (isascii(*vp) && isprint(*vp))
  128.             len++;
  129.         else
  130.             len += 4;
  131.     rp = result = (char *) palloc(len);
  132.     vp = vlena->vl_dat;
  133.     for (i = vlena->vl_len - sizeof(int32); i != 0; i--)    /* varlena? */
  134.         if (*vp == '\\') {
  135.             *vp++;
  136.             *rp++ = '\\';
  137.             *rp++ = '\\';
  138.         } else if (isascii(*vp) && isprint(*vp))
  139.             *rp++ = *vp++;
  140.         else {
  141.             val = *vp++;
  142.             *rp = '\\';
  143.             rp += 3;
  144.             *rp-- = DIG(val & 07);
  145.             val >>= 3;
  146.             *rp-- = DIG(val & 07);
  147.             val >>= 3;
  148.             *rp = DIG(val & 03);
  149.             rp += 3;
  150.         }
  151.     *rp = '\0';
  152.     return(result);
  153. }
  154.  
  155.  
  156. /*
  157.  *    textin        - converts "..." to internal representation
  158.  */
  159. struct varlena *
  160. textin(inputText)
  161.     char     *inputText;
  162. {
  163.     register struct varlena    *result;
  164.     register int        len;
  165.     extern            bcopy();
  166.  
  167.     if (inputText == NULL)
  168.         return(NULL);
  169.     len = strlen(inputText) + sizeof(int32);        /* varlena? */
  170.     result = (struct varlena *) palloc(len);
  171.     result->vl_len = len;
  172.     bcopy(inputText, result->vl_dat, len - sizeof(int32));    /* varlena? */
  173.     return(result);
  174. }
  175.  
  176. /*
  177.  *    textout        - converts internal representation to "..."
  178.  */
  179. char *
  180. textout(vlena)
  181.     struct varlena    *vlena;
  182. {
  183.     register int    len;
  184.     char        *result;
  185.     extern        bcopy();
  186.  
  187.     if (vlena == NULL) {
  188.         result = (char *) palloc(2);
  189.         result[0] = '-';
  190.         result[1] = '\0';
  191.         return(result);
  192.     }
  193.     len = vlena->vl_len - sizeof(int32);            /* varlena? */
  194.     result = (char *) palloc(len + 1);
  195.     bcopy(vlena->vl_dat, result, len);
  196.     result[len] = '\0';
  197.     return(result);
  198. }
  199.  
  200.  
  201.          /* ========== PUBLIC ROUTINES ========== */
  202.  
  203.  
  204. /*
  205.  *    texteq        - returns 1 iff arguments are equal
  206.  *    textne        - returns 1 iff arguments are not equal
  207.  */
  208. int32
  209. texteq(arg1, arg2)
  210.     struct varlena    *arg1, *arg2;
  211. {
  212.     register int    len;
  213.     register char    *a1p, *a2p;
  214.  
  215.     if (arg1 == NULL || arg2 == NULL)
  216.         return((int32) NULL);
  217.     if ((len = arg1->vl_len) != arg2->vl_len)
  218.         return((int32) 0);
  219.     a1p = arg1->vl_dat;
  220.     a2p = arg2->vl_dat;
  221.     /*
  222.      * Varlenas are stored as the total size (data + size variable)
  223.      * followed by the data.  The size variable is an int32 so the
  224.      * length of the data is the total length less sizeof(int32)
  225.      */
  226.     len -= sizeof(int32);
  227.     while (len-- != 0)
  228.         if (*a1p++ != *a2p++)
  229.             return((int32) 0);
  230.     return((int32) 1);
  231. }
  232.  
  233. int32
  234. textne(arg1, arg2)
  235.     struct varlena    *arg1, *arg2;
  236. {
  237.     return((int32) !texteq(arg1, arg2));
  238. }
  239.  
  240. int32
  241. text_lt(arg1, arg2)
  242.     struct varlena *arg1, *arg2;
  243. {
  244.     int len;
  245.     char *a1p, *a2p;
  246.  
  247.     if (arg1 == NULL || arg2 == NULL)
  248.         return((int32) 0);
  249.  
  250.     a1p = VARDATA(arg1);
  251.     a2p = VARDATA(arg2);
  252.  
  253.     if ((len = arg1->vl_len) > arg2->vl_len)
  254.         len = arg2->vl_len;
  255.     len -= sizeof(int32);
  256.  
  257.     while (len != 0 && *a1p == *a2p)
  258.     {
  259.         a1p++;
  260.         a2p++;
  261.         len--;
  262.     }
  263.     if (len)
  264.         return (int32) (*a1p < *a2p);
  265.     else
  266.         return (int32) (arg1->vl_len < arg2->vl_len);
  267. }
  268.  
  269. int32
  270. text_le(arg1, arg2)
  271.     struct varlena *arg1, *arg2;
  272. {
  273.     int len;
  274.     char *a1p, *a2p;
  275.  
  276.     if (arg1 == NULL || arg2 == NULL)
  277.         return((int32) 0);
  278.  
  279.     a1p = VARDATA(arg1);
  280.     a2p = VARDATA(arg2);
  281.  
  282.     if ((len = arg1->vl_len) > arg2->vl_len)
  283.         len = arg2->vl_len;
  284.     len -= sizeof(int32);                    /* varlena! */
  285.  
  286.     while (len != 0 && *a1p == *a2p)
  287.     {
  288.         a1p++;
  289.         a2p++;
  290.         len--;
  291.     }
  292.     if (len)
  293.         return (int32) (*a1p < *a2p);
  294.     else
  295.         return ((int32) VARSIZE(arg1) <= VARSIZE(arg2));
  296. }
  297.  
  298. int32
  299. text_gt(arg1, arg2)
  300.     struct varlena *arg1, *arg2;
  301. {
  302.     return ((int32) !text_le(arg1, arg2));
  303. }
  304.  
  305. int32
  306. text_ge(arg1, arg2)
  307.     struct varlena *arg1, *arg2;
  308. {
  309.     return ((int32) !text_lt(arg1, arg2));
  310. }
  311.  
  312. /*-------------------------------------------------------------
  313.  * byteaGetSize
  314.  *
  315.  * get the number of bytes contained in an instance of type 'bytea'
  316.  *-------------------------------------------------------------
  317.  */
  318. int32
  319. byteaGetSize(v)
  320. struct varlena *v;
  321. {
  322.     register int len;
  323.  
  324.     len = v->vl_len - sizeof(v->vl_len);
  325.  
  326.     return(len);
  327. }
  328.  
  329. /*-------------------------------------------------------------
  330.  * byteaGetByte
  331.  *
  332.  * this routine treats "bytea" as an array of bytes.
  333.  * It returns the Nth byte (a number between 0 and 255) or
  334.  * it dies if the length of this array is less than n.
  335.  *-------------------------------------------------------------
  336.  */
  337. int32
  338. byteaGetByte(v, n)
  339. struct varlena *v;
  340. int32 n;
  341. {
  342.     int len;
  343.     int byte;
  344.  
  345.     len = byteaGetSize(v);
  346.  
  347.     if (n>=len) {
  348.     elog(WARN, "byteaGetByte: index (=%d) out of range [0..%d]",
  349.         n,len-1);
  350.     }
  351.  
  352.     byte = (unsigned char) (v->vl_dat[n]);
  353.  
  354.     return((int32) byte);
  355. }
  356.  
  357. /*-------------------------------------------------------------
  358.  * byteaGetBit
  359.  *
  360.  * This routine treats a "bytea" type like an array of bits.
  361.  * It returns the value of the Nth bit (0 or 1).
  362.  * If 'n' is out of range, it dies!
  363.  *
  364.  *-------------------------------------------------------------
  365.  */
  366. int32
  367. byteaGetBit(v, n)
  368. struct varlena *v;
  369. int32 n;
  370. {
  371.     int len;
  372.     int byteNo, bitNo;
  373.     int byte;
  374.  
  375.     byteNo = n/8;
  376.     bitNo = n%8;
  377.  
  378.     byte = byteaGetByte(v, byteNo);
  379.  
  380.     if (byte & (1<<bitNo)) {
  381.     return((int32)1);
  382.     } else {
  383.     return((int32)0);
  384.     }
  385. }
  386. /*-------------------------------------------------------------
  387.  * byteaSetByte
  388.  *
  389.  * Given an instance of type 'bytea' creates a new one with
  390.  * the Nth byte set to the given value.
  391.  *
  392.  *-------------------------------------------------------------
  393.  */
  394.  
  395. struct varlena *
  396. byteaSetByte(v, n, newByte)
  397. struct varlena *v;
  398. int32 n;
  399. int32 newByte;
  400. {
  401.     int len;
  402.     struct varlena *res;
  403.     int i;
  404.  
  405.     len = byteaGetSize(v);
  406.  
  407.     if (n>=len) {
  408.     elog(WARN,
  409.         "byteaSetByte: index (=%d) out of range [0..%d]",
  410.         n, len-1);
  411.     }
  412.  
  413.     /*
  414.      * Make a copy of the original varlena.
  415.      */
  416.     res = (struct varlena *) palloc(VARSIZE(v));
  417.     if (res==NULL) {
  418.     elog(WARN, "byteaSetByte: Out of memory (%d bytes requested)",
  419.         VARSIZE(v));
  420.     }
  421.     bcopy((char *)v, (char *)res, VARSIZE(v));
  422.     
  423.     /*
  424.      *  Now set the byte.
  425.      */
  426.     res->vl_dat[n] = newByte;
  427.  
  428.     return(res);
  429. }
  430.  
  431. /*-------------------------------------------------------------
  432.  * byteaSetBit
  433.  *
  434.  * Given an instance of type 'bytea' creates a new one with
  435.  * the Nth bit set to the given value.
  436.  *
  437.  *-------------------------------------------------------------
  438.  */
  439.  
  440. struct varlena *
  441. byteaSetBit(v, n, newBit)
  442. struct varlena *v;
  443. int32 n;
  444. int32 newBit;
  445. {
  446.     struct varlena *res;
  447.     int oldByte, newByte;
  448.     int byteNo, bitNo;
  449.  
  450.     /*
  451.      * sanity check!
  452.      */
  453.     if (newBit != 0 && newBit != 1) {
  454.     elog(WARN, "byteaSetByte: new bit must be 0 or 1");
  455.     }
  456.  
  457.     /*
  458.      * get the byte where the bit we want is stored.
  459.      */
  460.     byteNo = n / 8;
  461.     bitNo = n % 8;
  462.     oldByte = byteaGetByte(v, byteNo);
  463.  
  464.     /*
  465.      * calculate the new value for that byte
  466.      */
  467.     if (newBit == 0) {
  468.     newByte = oldByte & (~(1<<bitNo));
  469.     } else {
  470.     newByte = oldByte | (1<<bitNo);
  471.     }
  472.  
  473.     /*
  474.      * NOTE: 'byteaSetByte' creates a copy of 'v' & sets the byte.
  475.      */
  476.     res = byteaSetByte(v, byteNo, newByte);
  477.  
  478.     return(res);
  479. }
  480.